#!/usr/env/bin python
"""
:mod:`pynchon.math.array`
=========================

Provides general purpose array functions.
"""
from __future__ import division
import numpy as np

def normalize_vector(array, axis=-1):
    """
    Normalize the vectors of A in the direction of axis. This means that each
    vector will have length 1. The default axis is the last.
    
    Arguments:
    
        - array (``numpy.ndarray``) A numpy array.
        - axis (``int``) The axis which will have vectors of lenght 1.
    """
    shape = list(array.shape)
    shape[axis] = 1
    length = np.sqrt((array*array).sum(axis))   
    out = array / length.reshape(shape)
    return out

def normalize_sum(array, axis=None):
    """
    Normalize the vectors of A in the direction of axis. This means that each
    vector will have sum of 1. The default is to normalize the whole array to 
    sum to one.
    
    Arguments:
    
        - array (``numpy.ndarray``) A numpy array.
        - axis (``int``) The axis which will be normalized to 1.
    """
    if axis is not None:
        sum_ = array.sum(axis =axis)
        out = (array.swapaxes(0, axis) / sum_).swapaxes(0, axis)
    else:
        sum_ = array.sum()
        out = array / sum_
    return out

def normalize_linear(array, r_min=0, r_max=1, axis=None):
    """
    Normalize the vectors of A in the direction of axis. This means that each
    vector will have values withing the range (r_min, r_max). The default is to 
    normalize the whole array to this range.
    
    f(x) = (x - d_min) / (d_max - d_min) * (r_max - r_min) + r_min
    
    Arguments:
    
        - array (``numpy.ndarray``) A numpy array.
        - r_min (``number``) The lower bound of the output. 
        - r_max (``number``) The upper bount of the output.
        - axis (``int``) The axis which will be normalized to the range defined
          by r_min, r_max.
    """
    r_rng = r_max - r_min
    d_min = array.min(axis=axis)
    d_max = array.max(axis=axis)
    d_rng = d_max - d_min
    if axis is None:
        out = (array - d_min) / d_rng * r_rng + r_min
    else:
        swapped = array.swapaxes(0, axis)
        out = ((swapped - d_min) / d_rng * r_rng  + r_min).swapaxes(0, axis)
    return out
    
def max_index(array):
    """
    """
    max_value = array.argmax()
    idx = np.unravel_index(max_value, array.shape)
    return idx
    
    
    
    

    
    
    
    
        